import { transform } from 'ol/proj'
import TileLayer from 'ol/layer/Tile'
import TileWMS from 'ol/source/TileWMS'
import WMTS from 'ol/source/WMTS'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { get as getProjection } from 'ol/proj'
import { getTopLeft, getWidth } from 'ol/extent'
import TileArcGISRest from 'ol/source/TileArcGISRest'
import ImageArcGISRest from 'ol/source/ImageArcGISRest'
import ImageLayer from 'ol/layer/Image'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import GeoJSON from 'ol/format/GeoJSON'
import { Style, Fill, Stroke, Circle, Text } from 'ol/style'
import MVT from 'ol/format/MVT'
import VectorTileLayer from 'ol/layer/VectorTile'
import VectorTileSource from 'ol/source/VectorTile'
import { createXYZ } from 'ol/tilegrid'
import Static from 'ol/source/ImageStatic'
import { getCenter } from 'ol/extent'
import Cluster from 'ol/source/Cluster'
import { Point } from 'ol/geom'
import { boundingExtent } from 'ol/extent'
import RegularShape from 'ol/style/RegularShape'
import { asArray } from 'ol/color'
import Feature from 'ol/Feature'
import { fromLonLat } from 'ol/proj'
import Heatmap from 'ol/layer/Heatmap'

// 坐标转换工具
export const transformCoordinate = (coord, fromProj, toProj) => {
  return transform(coord, fromProj, toProj)
}

// 格式化距离
export const formatLength = (length) => {
  if (length > 100) {
    return Math.round((length / 1000) * 100) / 100 + ' km'
  } else {
    return Math.round(length * 100) / 100 + ' m'
  }
}

// 格式化面积
export const formatArea = (area) => {
  if (area > 10000) {
    return Math.round((area / 1000000) * 100) / 100 + ' km²'
  } else {
    return Math.round(area * 100) / 100 + ' m²'
  }
}

// 创建默认样式
export const createDefaultStyle = (type) => {
  // 实现默认样式创建逻辑
}

/**
 * 创建 WMS 图层
 * @param {Object} options - WMS 图层配置选项
 * @param {string} options.url - WMS 服务地址
 * @param {string} options.layers - 图层名称
 * @param {string} options.title - 图层标题
 * @param {string} [options.format='image/png'] - 图片格式
 * @param {boolean} [options.transparent=true] - 是否透明
 * @param {string} [options.version='1.1.1'] - WMS 版本
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {TileLayer} WMS 图层实例
 */
export const createWMSLayer = ({
  url,
  layers,
  title,
  format = 'image/png',
  transparent = true,
  version = '1.1.1',
  opacity = 1,
  visible = true,
  zIndex
}) => {
  return new TileLayer({
    title,
    opacity,
    visible,
    zIndex,
    source: new TileWMS({
      url,
      params: {
        LAYERS: layers,
        FORMAT: format,
        TRANSPARENT: transparent,
        VERSION: version
      },
      crossOrigin: 'anonymous',
      projection: 'EPSG:4326',
      wrapX: true
    })
  })
}

/**
 * 创建 WMTS 图层
 * @param {Object} options - WMTS 图层配置选项
 * @param {string} options.url - WMTS 服务地址
 * @param {string} options.layer - 图层名称
 * @param {string} options.title - 图层标题
 * @param {string} [options.matrixSet='EPSG:4326'] - 矩阵集
 * @param {string} [options.format='image/png'] - 图片格式
 * @param {string} [options.style='default'] - 样式
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {TileLayer} WMTS 图层实例
 */
export const createWMTSLayer = ({
  url,
  layer,
  title,
  matrixSet = 'EPSG:4326',
  format = 'image/png',
  style = 'default',
  opacity = 1,
  visible = true,
  zIndex
}) => {
  const projection = getProjection(matrixSet)
  const projectionExtent = projection.getExtent()
  const size = getWidth(projectionExtent) / 256
  const resolutions = new Array(19)
  const matrixIds = new Array(19)
  
  for (let z = 0; z < 19; ++z) {
    resolutions[z] = size / Math.pow(2, z)
    matrixIds[z] = z
  }

  return new TileLayer({
    title,
    opacity,
    visible,
    zIndex,
    source: new WMTS({
      url,
      layer: layer,
      matrixSet: matrixSet,
      format: format,
      projection: projection,
      tileGrid: new WMTSTileGrid({
        origin: getTopLeft(projectionExtent),
        resolutions: resolutions,
        matrixIds: matrixIds
      }),
      style: style,
      wrapX: true,
      crossOrigin: 'anonymous'
    })
  })
}

/**
 * 批量创建 WMS 图层
 * @param {Array<Object>} layerConfigs - WMS 图层配置数组
 * @returns {Array<TileLayer>} WMS 图层数组
 */
export const createWMSLayers = (layerConfigs) => {
  return layerConfigs.map(config => createWMSLayer(config))
}

/**
 * 批量创建 WMTS 图层
 * @param {Array<Object>} layerConfigs - WMTS 图层配置数组
 * @returns {Array<TileLayer>} WMTS 图层数组
 */
export const createWMTSLayers = (layerConfigs) => {
  return layerConfigs.map(config => createWMTSLayer(config))
}

/**
 * 创建 ArcGIS MapServer 瓦片图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - MapServer 服务地址
 * @param {string} options.title - 图层标题
 * @param {Object} [options.params={}] - 请求参数
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @param {boolean} [options.useImage=false] - 是否使用 ImageLayer (单张图片)
 * @returns {TileLayer|ImageLayer} ArcGIS MapServer 图层实例
 */
export const createArcGISMapServerLayer = ({
  url,
  title,
  params = {},
  opacity = 1,
  visible = true,
  zIndex,
  useImage = false
}) => {
  // 基本配置
  const baseConfig = {
    title,
    opacity,
    visible,
    zIndex
  }

  // 源配置
  const sourceConfig = {
    url,
    crossOrigin: 'anonymous',
    projection: 'EPSG:4326',
    params: {
      FORMAT: 'PNG32',
      TRANSPARENT: true,
      ...params
    }
  }

  // 根据 useImage 参数决定使用 TileLayer 还是 ImageLayer
  if (useImage) {
    return new ImageLayer({
      ...baseConfig,
      source: new ImageArcGISRest(sourceConfig)
    })
  } else {
    return new TileLayer({
      ...baseConfig,
      source: new TileArcGISRest(sourceConfig)
    })
  }
}

/**
 * 创建 ArcGIS MapServer 动态图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - MapServer 服务��址
 * @param {string} options.title - 图层标题
 * @param {Array<number>} [options.layers] - 要显示的图层ID数组
 * @param {string} [options.where] - SQL 查询条件
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {ImageLayer} ArcGIS MapServer 动态图层实例
 */
export const createArcGISDynamicLayer = ({
  url,
  title,
  layers,
  where,
  opacity = 1,
  visible = true,
  zIndex
}) => {
  const layerDefs = {}
  if (where && layers) {
    layers.forEach(layerId => {
      layerDefs[layerId] = where
    })
  }

  return new ImageLayer({
    title,
    opacity,
    visible,
    zIndex,
    source: new ImageArcGISRest({
      url,
      crossOrigin: 'anonymous',
      projection: 'EPSG:4326',
      params: {
        FORMAT: 'PNG32',
        TRANSPARENT: true,
        LAYERS: layers ? `show:${layers.join(',')}` : 'show:all',
        layerDefs: layerDefs && Object.keys(layerDefs).length > 0 ? JSON.stringify(layerDefs) : undefined
      }
    })
  })
}

/**
 * 批量创建 ArcGIS MapServer 图层
 * @param {Array<Object>} layerConfigs - 图层配置数组
 * @param {boolean} [dynamic=false] - 是否创建动态图层
 * @returns {Array<TileLayer|ImageLayer>} ArcGIS MapServer 图层数组
 */
export const createArcGISLayers = (layerConfigs, dynamic = false) => {
  return layerConfigs.map(config => 
    dynamic ? createArcGISDynamicLayer(config) : createArcGISMapServerLayer(config)
  )
}

/**
 * 创建默认的 GeoJSON 样式
 * @param {Object} options - 样式配置选项
 * @param {string} [options.fillColor='rgba(255,255,255,0.4)'] - 填充颜色
 * @param {string} [options.strokeColor='#3399CC'] - 边框颜色
 * @param {number} [options.strokeWidth=1.5] - 边框宽度
 * @param {string} [options.labelField] - 标注字段名
 * @param {Object} [options.labelStyle] - 标注样式
 * @returns {Style} OpenLayers 样式对象
 */
export const createGeoJSONStyle = ({
  fillColor = 'rgba(255,255,255,0.4)',
  strokeColor = '#3399CC',
  strokeWidth = 1.5,
  labelField,
  labelStyle = {}
}) => {
  return (feature) => {
    const style = new Style({
      fill: new Fill({
        color: fillColor
      }),
      stroke: new Stroke({
        color: strokeColor,
        width: strokeWidth
      }),
      image: new Circle({
        radius: 7,
        fill: new Fill({
          color: fillColor
        }),
        stroke: new Stroke({
          color: strokeColor,
          width: strokeWidth
        })
      })
    })

    if (labelField) {
      const text = feature.get(labelField)
      if (text) {
        style.setText(new Text({
          text: text.toString(),
          font: '12px Arial',
          fill: new Fill({
            color: '#000'
          }),
          stroke: new Stroke({
            color: '#fff',
            width: 2
          }),
          offsetY: -15,
          ...labelStyle
        }))
      }
    }

    return style
  }
}

/**
 * 创建 GeoJSON 图层
 * @param {Object} options - 图层配置选项
 * @param {string|Object} options.data - GeoJSON 数据的 URL 或对象
 * @param {string} options.title - 图层标题
 * @param {Object} [options.style] - 样式配置
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {Promise<VectorLayer>} GeoJSON 图层实例
 */
export const createGeoJSONLayer = async ({
  data,
  title,
  style = {},
  opacity = 1,
  visible = true,
  zIndex
}) => {
  try {
    let geoJSONData
    if (typeof data === 'string') {
      // 如果是 URL，则获取数据
      const response = await fetch(data)
      geoJSONData = await response.json()
    } else {
      // 如果是对象，直接使用
      geoJSONData = data
    }

    const vectorSource = new VectorSource({
      features: new GeoJSON().readFeatures(geoJSONData, {
        featureProjection: 'EPSG:4326'
      })
    })

    return new VectorLayer({
      title,
      opacity,
      visible,
      zIndex,
      source: vectorSource,
      style: createGeoJSONStyle(style)
    })
  } catch (error) {
    console.error('创建 GeoJSON 图层失败:', error)
    throw error
  }
}

/**
 * 批量创建 GeoJSON 图层
 * @param {Array<Object>} layerConfigs - 图层配置数组
 * @returns {Promise<Array<VectorLayer>>} GeoJSON 图层数组
 */
export const createGeoJSONLayers = async (layerConfigs) => {
  try {
    return await Promise.all(layerConfigs.map(config => createGeoJSONLayer(config)))
  } catch (error) {
    console.error('批量创建 GeoJSON 图层失败:', error)
    throw error
  }
}

/**
 * 创建 MVT 图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - MVT 服务地址，支持 {z}/{x}/{y} 占位符
 * @param {string} options.title - 图层标题
 * @param {Object|Function} [options.style] - 样式配置或样式函数
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @param {number} [options.minZoom=0] - 最小缩放级别
 * @param {number} [options.maxZoom=22] - 最大缩放级别
 * @returns {VectorTileLayer} MVT 图层实例
 */
export const createMVTLayer = ({
  url,
  title,
  style,
  opacity = 1,
  visible = true,
  zIndex,
  minZoom = 0,
  maxZoom = 22
}) => {
  // 创建瓦片网格
  const tileGrid = createXYZ({
    minZoom,
    maxZoom,
    tileSize: 512
  })

  // 创建默认样式
  const defaultStyle = createGeoJSONStyle({
    fillColor: 'rgba(255,255,255,0.4)',
    strokeColor: '#3399CC',
    strokeWidth: 1
  })

  return new VectorTileLayer({
    title,
    opacity,
    visible,
    zIndex,
    source: new VectorTileSource({
      format: new MVT(),
      url,
      tileGrid,
      maxZoom,
      minZoom,
      crossOrigin: 'anonymous'
    }),
    style: style || defaultStyle,
    declutter: true // 启用标注避让
  })
}

/**
 * 创建 Mapbox 样式的 MVT 图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - Mapbox 样式 URL 或样式对象
 * @param {string} options.title - 图层标题
 * @param {string} [options.accessToken] - Mapbox access token
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {Promise<VectorTileLayer[]>} MVT 图层��组
 */
export const createMapboxMVTLayers = async ({
  url,
  title,
  accessToken,
  opacity = 1,
  visible = true,
  zIndex
}) => {
  try {
    // 获取 Mapbox 样式
    let style
    if (typeof url === 'string') {
      const response = await fetch(url + (accessToken ? `?access_token=${accessToken}` : ''))
      style = await response.json()
    } else {
      style = url
    }

    // 创建图层数组
    const layers = []
    
    // 处理每个源
    for (const [sourceId, source] of Object.entries(style.sources)) {
      if (source.type === 'vector') {
        // 处理矢量瓦片源
        const sourceUrl = source.tiles?.[0] || 
          `https://{a-d}.tiles.mapbox.com/v4/${source.url}/{z}/{x}/{y}.mvt` +
          (accessToken ? `?access_token=${accessToken}` : '')

        const layer = createMVTLayer({
          url: sourceUrl,
          title: `${title} - ${sourceId}`,
          opacity,
          visible,
          zIndex: zIndex ? zIndex + layers.length : undefined,
          style: (feature) => {
            // 这里可以根据 Mapbox 样式规范实现样式转换
            // 简单起见，使用默认样式
            return createGeoJSONStyle({})
          }
        })

        layers.push(layer)
      }
    }

    return layers
  } catch (error) {
    console.error('创建 Mapbox MVT 图层失败:', error)
    throw error
  }
}

/**
 * 批量创建 MVT 图层
 * @param {Array<Object>} layerConfigs - 图层配置数组
 * @returns {Array<VectorTileLayer>} MVT 图层数组
 */
export const createMVTLayers = (layerConfigs) => {
  return layerConfigs.map(config => createMVTLayer(config))
}

/**
 * 创建静态图片图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - 图片URL
 * @param {string} options.title - 图层标题
 * @param {Array<number>} options.extent - 图片范围 [minX, minY, maxX, maxY]
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @param {string} [options.projection='EPSG:4326'] - 投影坐标系
 * @returns {Promise<ImageLayer>} 静态图片图层实例
 */
export const createStaticImageLayer = async ({
  url,
  title,
  extent,
  opacity = 1,
  visible = true,
  zIndex,
  projection = 'EPSG:4326'
}) => {
  try {
    // 验证参数
    if (!url || !extent || extent.length !== 4) {
      throw new Error('无效的图片URL或范围参数')
    }

    // 创建图片元素并等待加载完成
    const image = new Image()
    await new Promise((resolve, reject) => {
      image.onload = resolve
      image.onerror = () => reject(new Error('图片加载失败'))
      image.crossOrigin = 'anonymous'
      image.src = url
    })

    // 创建静态图片图层
    return new ImageLayer({
      title,
      opacity,
      visible,
      zIndex,
      source: new Static({
        url: url,
        crossOrigin: 'anonymous',
        projection: projection,
        imageExtent: extent,
        imageLoadFunction: (image, src) => {
          image.getImage().src = src
        }
      })
    })
  } catch (error) {
    console.error('创建静态图片图层失败:', error)
    throw error
  }
}

/**
 * 创建带有缩略图的静态图片图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - 高分辨率图片URL
 * @param {string} options.thumbnailUrl - 缩略图URL
 * @param {string} options.title - 图层标题
 * @param {Array<number>} options.extent - 图片范围 [minX, minY, maxX, maxY]
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @param {string} [options.projection='EPSG:4326'] - 投影坐标系
 * @returns {Promise<ImageLayer>} 静态图片图层实例
 */
export const createStaticImageLayerWithThumbnail = async ({
  url,
  thumbnailUrl,
  title,
  extent,
  opacity = 1,
  visible = true,
  zIndex,
  projection = 'EPSG:4326'
}) => {
  try {
    const layer = await createStaticImageLayer({
      url: thumbnailUrl || url,
      title,
      extent,
      opacity,
      visible,
      zIndex,
      projection
    })

    if (thumbnailUrl) {
      // 预加载高分辨率图片
      const highResImage = new Image()
      highResImage.crossOrigin = 'anonymous'
      highResImage.src = url

      highResImage.onload = () => {
        // 高分辨率图片加载完成后替换源
        layer.setSource(
          new Static({
            url: url,
            crossOrigin: 'anonymous',
            projection: projection,
            imageExtent: extent
          })
        )
      }
    }

    return layer
  } catch (error) {
    console.error('创建带缩略图的静态图片图层失败:', error)
    throw error
  }
}

/**
 * 批量创建静态图片图层
 * @param {Array<Object>} layerConfigs - 图层配置数组
 * @param {boolean} [useThumbnail=false] - 是否使用缩略图
 * @returns {Promise<Array<ImageLayer>>} 静态图片图层数组
 */
export const createStaticImageLayers = async (layerConfigs, useThumbnail = false) => {
  try {
    return await Promise.all(
      layerConfigs.map(config => 
        useThumbnail ? 
          createStaticImageLayerWithThumbnail(config) : 
          createStaticImageLayer(config)
      )
    )
  } catch (error) {
    console.error('批量创建静态图片图层失败:', error)
    throw error
  }
}

/**
 * 移动图层的索引
 * @param {import('ol/Map').default} map - OpenLayers 地图实例
 * @param {import('ol/layer/Base').default} layer - 要移动的图层
 * @param {number} newIndex - 新的索引位置
 * @param {boolean} [relative=false] - 是否是相对移动（true: 相对当前位置移动，false: 移动到指定位置）
 */
export const moveLayerIndex = (map, layer, newIndex, relative = false) => {
  try {
    const layers = map.getLayers()
    const currentIndex = layers.getArray().indexOf(layer)
    
    if (currentIndex === -1) {
      throw new Error('图层不存在于地图中')
    }

    // 计算目标索引
    let targetIndex = relative ? currentIndex + newIndex : newIndex
    
    // 确保索引在有效范围内
    targetIndex = Math.max(0, Math.min(targetIndex, layers.getLength() - 1))
    
    if (targetIndex !== currentIndex) {
      // 移除图层并在新位置插入
      layers.removeAt(currentIndex)
      layers.insertAt(targetIndex, layer)
      
      // 更新图层的 zIndex
      const allLayers = layers.getArray()
      allLayers.forEach((layer, index) => {
        layer.setZIndex(index)
      })
    }
  } catch (error) {
    console.error('移动图层索引失败:', error)
    throw error
  }
}

/**
 * 改变图层可见性
 * @param {import('ol/Map').default} map - OpenLayers 地图实例
 * @param {string|import('ol/layer/Base').default} layerOrTitle - 图层实例或图层标题
 * @param {boolean} [visible] - 是否可见，不传则切换当前状态
 * @returns {boolean} 图层的新可见状态
 */
export const toggleLayerVisibility = (map, layerOrTitle, visible) => {
  try {
    let layer
    
    if (typeof layerOrTitle === 'string') {
      // 通过标题查找图层
      layer = map.getLayers().getArray().find(l => l.get('title') === layerOrTitle)
      if (!layer) {
        throw new Error(`未找到标题为 "${layerOrTitle}" 的图层`)
      }
    } else {
      layer = layerOrTitle
    }

    // 如果没有指定 visible，则切换当前状态
    const newVisibility = visible === undefined ? !layer.getVisible() : visible
    layer.setVisible(newVisibility)
    
    return newVisibility
  } catch (error) {
    console.error('改变图层可见性失败:', error)
    throw error
  }
}

/**
 * 创建聚合图层
 * @param {Object} options - 图层配置选项
 * @param {string|Object} options.data - GeoJSON 数据的 URL 或对象
 * @param {string} options.title - 图层标题
 * @param {number} [options.distance=40] - 聚合距离（像素）
 * @param {number} [options.minDistance=20] - 最小聚合距离（像素）
 * @param {Object} [options.style] - 样式配置
 * @param {Object} [options.clusterStyle] - ��合点样式配置
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {Promise<VectorLayer>} 聚合图层实例
 */
export const createClusterLayer = async ({
  data,
  title,
  distance = 40,
  minDistance = 20,
  style = {},
  clusterStyle = {},
  opacity = 1,
  visible = true,
  zIndex
}) => {
  try {
    // 创建基础矢量图层
    const sourceLayer = await createGeoJSONLayer({
      data,
      title,
      style,
      opacity,
      visible,
      zIndex
    })

    // 创建聚合源
    const clusterSource = new Cluster({
      distance,
      minDistance,
      source: sourceLayer.getSource()
    })

    // 创建聚合样式函数
    const createClusterStyle = (feature) => {
      const size = feature.get('features').length
      const {
        fillColor = 'rgba(255,153,0,0.8)',
        strokeColor = '#fff',
        strokeWidth = 2,
        textColor = '#fff',
        minRadius = 10,
        maxRadius = 30,
        font = '12px Arial'
      } = clusterStyle

      // 计算圆的半径（根据聚合点数量动态计算）
      const radius = Math.min(maxRadius, Math.max(minRadius, Math.sqrt(size) * 5))

      return new Style({
        image: new Circle({
          radius: radius,
          fill: new Fill({
            color: fillColor
          }),
          stroke: new Stroke({
            color: strokeColor,
            width: strokeWidth
          })
        }),
        text: new Text({
          text: size.toString(),
          fill: new Fill({
            color: textColor
          }),
          font: font
        })
      })
    }

    // 创建聚合图层
    const clusterLayer = new VectorLayer({
      title,
      opacity,
      visible,
      zIndex,
      source: clusterSource,
      style: (feature) => {
        const features = feature.get('features')
        // 如果只有一个点，使用原始样式
        if (features.length === 1) {
          return createGeoJSONStyle(style)(features[0])
        }
        // 否则使用聚合样式
        return createClusterStyle(feature)
      }
    })

    // 添加点击事件处理
    clusterLayer.set('handleClick', (event, map) => {
      const feature = map.forEachFeatureAtPixel(event.pixel, f => f)
      if (feature) {
        const features = feature.get('features')
        if (features.length > 1) {
          // 获取聚合点的范围
          const extent = boundingExtent(
            features.map(f => {
              const geometry = f.getGeometry()
              return geometry instanceof Point ? geometry.getCoordinates() : geometry.getFirstCoordinate()
            })
          )
          
          // 放大到聚合点范围
          map.getView().fit(extent, {
            duration: 500,
            padding: [50, 50, 50, 50]
          })
        }
      }
    })

    return clusterLayer
  } catch (error) {
    console.error('创建聚合图层失败:', error)
    throw error
  }
}

/**
 * 创建形状图层
 * @param {Object} options - 形状配置选项
 * @param {string} options.type - 形状类型：'cross'(十字形), 'x'(X形), 'star'(星形), 'triangle'(三角形), 'square'(正方形), 'rectangle'(矩形)
 * @param {Array<number>} options.coordinate - 坐标 [lon, lat]
 * @param {Object} [options.style] - 样式配置
 * @param {string} [options.style.fillColor='rgba(255,0,0,0.4)'] - 填充颜色
 * @param {string} [options.style.strokeColor='#ff0000'] - 边框颜色
 * @param {number} [options.style.strokeWidth=2] - 边框宽度
 * @param {number} [options.style.size=20] - 形状大小
 * @param {number} [options.style.rotation=0] - 旋转角度（弧度）
 * @returns {Feature} OpenLayers 要素
 */
export const createShapeFeature = ({
  type,
  coordinate,
  style = {}
}) => {
  const {
    fillColor = 'rgba(255,0,0,0.4)',
    strokeColor = '#ff0000',
    strokeWidth = 2,
    size = 20,
    rotation = 0
  } = style

  // 创建基本样式配置
  const baseStyle = {
    fill: new Fill({
      color: fillColor
    }),
    stroke: new Stroke({
      color: strokeColor,
      width: strokeWidth
    }),
    rotation: rotation
  }

  // 根据类型创建不同的形状样式
  let shapeStyle
  switch (type.toLowerCase()) {
    case 'cross': // 十字形
      shapeStyle = new Style({
        image: new RegularShape({
          ...baseStyle,
          points: 4,
          radius: size / 2,
          radius2: 0,
          angle: 0
        })
      })
      break

    case 'x': // X形
      shapeStyle = new Style({
        image: new RegularShape({
          ...baseStyle,
          points: 4,
          radius: size / 2,
          radius2: 0,
          angle: Math.PI / 4
        })
      })
      break

    case 'star': // 星形
      shapeStyle = new Style({
        image: new RegularShape({
          ...baseStyle,
          points: 5,
          radius: size / 2,
          radius2: size / 4,
          angle: 0
        })
      })
      break

    case 'triangle': // 三角形
      shapeStyle = new Style({
        image: new RegularShape({
          ...baseStyle,
          points: 3,
          radius: size / 2,
          angle: 0
        })
      })
      break

    case 'square': // 正方形
      shapeStyle = new Style({
        image: new RegularShape({
          ...baseStyle,
          points: 4,
          radius: size / 2,
          angle: Math.PI / 4
        })
      })
      break

    case 'rectangle': // 矩形
      shapeStyle = new Style({
        image: new RegularShape({
          ...baseStyle,
          points: 4,
          radius: size / 2,
          radius2: size / 3,
          angle: 0
        })
      })
      break

    default:
      throw new Error(`不支持的形状类型: ${type}`)
  }

  // 创建要素
  const feature = new Feature({
    geometry: new Point(fromLonLat(coordinate))
  })
  feature.setStyle(shapeStyle)

  return feature
}

/**
 * 创建形状图层
 * @param {Object} options - 图层配置选项
 * @param {Array<Object>} options.shapes - 形状配置数组
 * @param {string} options.title - 图层标题
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {VectorLayer} 矢量图层实例
 */
export const createShapeLayer = ({
  shapes,
  title,
  opacity = 1,
  visible = true,
  zIndex
}) => {
  try {
    // 创建要素
    const features = shapes.map(shape => createShapeFeature(shape))

    // 创建图层
    return new VectorLayer({
      title,
      opacity,
      visible,
      zIndex,
      source: new VectorSource({
        features: features
      })
    })
  } catch (error) {
    console.error('创建形状图层失败:', error)
    throw error
  }
}

/**
 * 创建热力图图层
 * @param {Object} options - 图层配置选项
 * @param {Array<Object>|string} options.data - 热力图数据数组或GeoJSON URL
 * @param {string} options.title - 图层标题
 * @param {Object} [options.heatmap] - 热力图配置
 * @param {number} [options.heatmap.radius=8] - 热力点半径（像素）
 * @param {number} [options.heatmap.blur=15] - 模糊半径（像素）
 * @param {Array<string>} [options.heatmap.gradient] - 渐变色数组
 * @param {string} [options.weightField='weight'] - 权重字段名
 * @param {number} [options.minWeight] - 最小权重值
 * @param {number} [options.maxWeight] - 最大权重值
 * @param {number} [options.opacity=1] - 图层透明度
 * @param {boolean} [options.visible=true] - 图层是否可见
 * @param {number} [options.zIndex] - 图层层级
 * @returns {Promise<Heatmap>} 热力图图层实例
 */
export const createHeatmapLayer = async ({
  data,
  title,
  heatmap = {},
  weightField = 'weight',
  minWeight,
  maxWeight,
  opacity = 1,
  visible = true,
  zIndex
}) => {
  try {
    // 处理数据源
    let features
    if (typeof data === 'string') {
      // 如果是URL，加载GeoJSON数据
      const response = await fetch(data)
      const geoJSON = await response.json()
      features = new GeoJSON().readFeatures(geoJSON, {
        featureProjection: 'EPSG:4326'
      })
    } else if (Array.isArray(data)) {
      // 如果是数组，转换为要素
      features = data.map(item => {
        return new Feature({
          geometry: new Point(fromLonLat(item.coordinate)),
          weight: item.weight || 1,
          ...item
        })
      })
    } else {
      throw new Error('无效的数据格式')
    }

    // 计算权重范围
    if (minWeight === undefined || maxWeight === undefined) {
      const weights = features.map(f => f.get(weightField) || 0)
      minWeight = minWeight ?? Math.min(...weights)
      maxWeight = maxWeight ?? Math.max(...weights)
    }

    // 创建热力图图层
    const {
      radius = 8,
      blur = 15,
      gradient = [
        'rgba(0,0,255,0)',
        'rgba(0,0,255,1)',
        'rgba(0,255,255,1)',
        'rgba(0,255,0,1)',
        'rgba(255,255,0,1)',
        'rgba(255,0,0,1)'
      ]
    } = heatmap

    return new Heatmap({
      title,
      opacity,
      visible,
      zIndex,
      source: new VectorSource({
        features: features
      }),
      blur: blur,
      radius: radius,
      gradient: gradient,
      weight: feature => {
        const weight = feature.get(weightField) || 0
        // 归一化权重值到 0-1 范围
        return (weight - minWeight) / (maxWeight - minWeight)
      }
    })
  } catch (error) {
    console.error('创建热力图图层失败:', error)
    throw error
  }
}

/**
 * 更新热力图数据
 * @param {Heatmap} layer - 热力图图层
 * @param {Array<Object>} data - 新的热力图数据
 * @param {Object} [options] - 更新选项
 * @param {string} [options.weightField='weight'] - 权重字段名
 * @param {number} [options.minWeight] - 最小权重值
 * @param {number} [options.maxWeight] - 最大权重值
 */
export const updateHeatmapData = (layer, data, {
  weightField = 'weight',
  minWeight,
  maxWeight
} = {}) => {
  try {
    // 转换数据为要素
    const features = data.map(item => {
      return new Feature({
        geometry: new Point(fromLonLat(item.coordinate)),
        weight: item.weight || 1,
        ...item
      })
    })

    // 计算权重范围
    if (minWeight === undefined || maxWeight === undefined) {
      const weights = features.map(f => f.get(weightField) || 0)
      minWeight = minWeight ?? Math.min(...weights)
      maxWeight = maxWeight ?? Math.max(...weights)
    }

    // 更新图层源和权重函数
    layer.setSource(new VectorSource({ features }))
    layer.setWeight(feature => {
      const weight = feature.get(weightField) || 0
      return (weight - minWeight) / (maxWeight - minWeight)
    })
  } catch (error) {
    console.error('更新热力图数据失败:', error)
    throw error
  }
}

/**
 * 删除地图图层
 * @param {import('ol/Map').default} map - OpenLayers 地图实例
 * @param {string|import('ol/layer/Base').default|Array<string|import('ol/layer/Base').default>} layerOrTitle - 图层实例、图层标题或它们的数组
 * @param {Object} [options] - 删除选项
 * @param {boolean} [options.removeSource=true] - 是否同时移除图层源
 * @param {boolean} [options.dispose=true] - 是否销毁图层
 * @returns {Array<import('ol/layer/Base').default>} 被删除的图层数组
 */
export const removeLayers = (map, layerOrTitle, {
  removeSource = true,
  dispose = true
} = {}) => {
  try {
    // 将单个图层转换为数组
    const layersToRemove = Array.isArray(layerOrTitle) ? layerOrTitle : [layerOrTitle]
    const removedLayers = []

    layersToRemove.forEach(item => {
      let layer
      if (typeof item === 'string') {
        // 通过标题查找图层
        layer = map.getLayers().getArray().find(l => l.get('title') === item)
        if (!layer) {
          console.warn(`未找到标题为 "${item}" 的图层`)
          return
        }
      } else {
        layer = item
      }

      // 从地图中移除图层
      map.removeLayer(layer)
      removedLayers.push(layer)

      // 清理图层源
      if (removeSource) {
        const source = layer.getSource()
        if (source) {
          if (source.clear) {
            source.clear()
          }
          if (source.dispose) {
            source.dispose()
          }
        }
      }

      // 销毁图层
      if (dispose && layer.dispose) {
        layer.dispose()
      }
    })

    return removedLayers
  } catch (error) {
    console.error('删除图层失败:', error)
    throw error
  }
}

/**
 * 删除所有图层
 * @param {import('ol/Map').default} map - OpenLayers 地图实例
 * @param {Object} [options] - 删除选项
 * @param {boolean} [options.keepBasemap=true] - 是否保留底图
 * @param {Array<string>} [options.excludeTitles=[]] - 要排除的图层标题数组
 * @param {boolean} [options.removeSource=true] - 是否同时移除图层源
 * @param {boolean} [options.dispose=true] - 是否销毁图层
 * @returns {Array<import('ol/layer/Base').default>} 被删除的图层数组
 */
export const removeAllLayers = (map, {
  keepBasemap = true,
  excludeTitles = [],
  removeSource = true,
  dispose = true
} = {}) => {
  try {
    const layers = map.getLayers().getArray()
    const layersToRemove = layers.filter(layer => {
      const title = layer.get('title')
      // 如果保留底图且是第一个图层，则跳过
      if (keepBasemap && layers.indexOf(layer) === 0) {
        return false
      }
      // 如果图层标题在排除列表中，则跳过
      if (excludeTitles.includes(title)) {
        return false
      }
      return true
    })

    return removeLayers(map, layersToRemove, { removeSource, dispose })
  } catch (error) {
    console.error('删除所有图层失败:', error)
    throw error
  }
}
/**
 * 修改图层或要素的样式
 * @param {import('ol/layer/Base').default|import('ol/Feature').default} target - 目标图层或要素
 * @param {Object} styleConfig - 样式配置
 * @param {Object} [options] - 配置选项
 * @param {boolean} [options.isTemporary=false] - 是否为临时样式
 * @param {number} [options.duration] - 临时样式持续时间(毫秒)
 * @param {Function} [options.onComplete] - 临时样式结束后的回调函数
 * @param {string} [options.type='default'] - 样式类型：'default'|'highlight'|'selected'|'custom'
 */
export const updateStyle = (target, styleConfig, {
  isTemporary = false,
  duration,
  onComplete,
  type = 'default'
} = {}) => {
  try {
    // 创建新样式
    const createNewStyle = () => {
      const {
        // 通用样式配置
        fillColor,
        strokeColor,
        strokeWidth,
        // 点样式配置
        radius,
        // 文本样式配置
        text,
        textColor,
        textStroke,
        textOffset,
        font,
        // 图标样式配置
        iconUrl,
        iconScale,
        iconAnchor,
        // 自定义样式函数
        customStyleFunction
      } = styleConfig

      // 如果提供了自定义样式函数，直接使用
      if (customStyleFunction) {
        return customStyleFunction(target)
      }

      // 创建基本样式
      const style = new Style({
        fill: fillColor ? new Fill({ color: fillColor }) : undefined,
        stroke: strokeColor ? new Stroke({
          color: strokeColor,
          width: strokeWidth || 1
        }) : undefined
      })

      // 添加点样式
      if (radius) {
        style.setImage(new Circle({
          radius: radius,
          fill: fillColor ? new Fill({ color: fillColor }) : undefined,
          stroke: strokeColor ? new Stroke({
            color: strokeColor,
            width: strokeWidth || 1
          }) : undefined
        }))
      }

      // 添加文本样式
      if (text) {
        style.setText(new Text({
          text: typeof text === 'function' ? text(target) : text,
          fill: new Fill({ color: textColor || '#000' }),
          stroke: textStroke ? new Stroke(textStroke) : undefined,
          offsetX: textOffset?.x || 0,
          offsetY: textOffset?.y || 0,
          font: font || '12px Arial'
        }))
      }

      // 添加图标样式
      if (iconUrl) {
        style.setImage(new Icon({
          src: iconUrl,
          scale: iconScale || 1,
          anchor: iconAnchor || [0.5, 0.5]
        }))
      }

      return style
    }

    // 保存原始样式（如果是临时样式）
    let originalStyle
    if (isTemporary) {
      originalStyle = target instanceof Feature ? 
        target.getStyle() : 
        target.getStyle()?.clone()
    }

    // 应用新样式
    const newStyle = createNewStyle()
    if (target instanceof Feature) {
      target.setStyle(newStyle)
    } else {
      target.setStyle(newStyle)
    }

    // 如果是临时样式，设置定时器恢复原样式
    if (isTemporary && duration) {
      setTimeout(() => {
        if (target instanceof Feature) {
          target.setStyle(originalStyle)
        } else {
          target.setStyle(originalStyle)
        }
        onComplete?.()
      }, duration)
    }

    // 存储样式类型
    target.set('styleType', type)

  } catch (error) {
    console.error('更新样式失败:', error)
    throw error
  }
}

/**
 * 批量更新要素样式
 * @param {Array<import('ol/Feature').default>} features - 要素数组
 * @param {Object|Function} styleConfig - 样式配置或样式函数
 * @param {Object} [options] - 配置选项
 */
export const updateFeaturesStyle = (features, styleConfig, options = {}) => {
  features.forEach(feature => {
    updateStyle(feature, 
      typeof styleConfig === 'function' ? styleConfig(feature) : styleConfig, 
      options
    )
  })
}

// 使用示例：
/*
// 修改单个要素样式
updateStyle(feature, {
  fillColor: 'rgba(255,0,0,0.5)',
  strokeColor: '#ff0000',
  strokeWidth: 2,
  text: feature => feature.get('name'),
  textColor: '#000',
  textOffset: { x: 0, y: 20 }
})

// 临时高亮显示
updateStyle(feature, {
  fillColor: 'rgba(255,255,0,0.5)',
  strokeColor: '#ffff00',
  strokeWidth: 3
}, {
  isTemporary: true,
  duration: 2000,
  onComplete: () => console.log('高亮结束'),
  type: 'highlight'
})

// 修改图层样式
updateStyle(layer, {
  fillColor: 'rgba(0,255,0,0.5)',
  strokeColor: '#00ff00',
  strokeWidth: 2
})

// 使用自定义样式函数
updateStyle(feature, {
  customStyleFunction: (feature) => {
    return new Style({
      // 自定义样式配置
    })
  }
})

// 批量更新要素样式
updateFeaturesStyle(features, {
  fillColor: 'rgba(0,0,255,0.5)',
  strokeColor: '#0000ff'
})

// 批量更新要素样式（使用函数）
updateFeaturesStyle(features, feature => ({
  fillColor: feature.get('type') === 'important' ? 'red' : 'blue',
  strokeColor: '#000'
}))
*/